﻿using Microsoft.Phone.Controls;
using Microsoft.Phone.Shell;
using NiklasKarl.WarpCam.Models;
using NiklasKarl.WarpCam.Native;
using NiklasKarl.WarpCam.Sources;
using System;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Navigation;

namespace NiklasKarl.WarpCam.Pages
{
    public partial class MainPage : PhoneApplicationPage
    {
        private ITiledPreview m_renderer;

        private int m_effectIndex;
        
        private PhoneApplicationFrame m_frame;
        private object m_frameContentWhenOpened;
        private CapturePage m_capturePage;


        public MainPage()
        {
            InitializeComponent();
            InitializeApplicationBar();

            TiltEffect.TiltableItems.Add(typeof(Border));
            m_effectIndex = -1;
        }

        private void InitializeApplicationBar()
        {
            if (AppModel.LocationSwitchPossible)
            {
                ApplicationBarIconButton switchButton = new ApplicationBarIconButton(new Uri("/Assets/AppBar/feature.frontcamera.png", UriKind.Relative));
                switchButton.Text = "switch";
                switchButton.Click += SwitchButton_Click;

                ApplicationBar.Buttons.Add(switchButton);
            }
        }

        protected override async void OnNavigatedTo(NavigationEventArgs e)
        {
            if (m_renderer != null)
            {
                if (m_renderer.PreviewSource != App.Model.CameraSource)
                {
                    m_renderer.PreviewSource = null;

                    await SetCameraSourceAsync();
                }
            }

            base.OnNavigatedTo(e);
        }

        protected override void OnNavigatedFrom(NavigationEventArgs e)
        {
            base.OnNavigatedFrom(e);
        }


        private async void LayoutRoot_Loaded(object sender, RoutedEventArgs e)
        {
            if (m_renderer == null)
            {
                SetStatus(true, "Initializing...");

                InitializePreviewRenderer();

                await SetCameraSourceAsync();

                SetStatus(false, null);
            }
        }


        private void InitializePreviewRenderer()
        {
            AppModel model = App.Model;

            /*m_source = new TiledViewfinderSource();

            for (int i = 0; i < 9; i++)
            {
                if (i != 4)
                {
                    m_source.SetEffect(i, model.Effects[i]);
                }
            }*/

            PreviewFactory factory = new PreviewFactory();
            m_renderer = factory.CreateTiledPreview();
            m_renderer.Resolution = new Windows.Foundation.Size(
                LayoutRoot.ActualWidth,
                LayoutRoot.ActualHeight
                );
            m_renderer.PreviewRect = new Windows.Foundation.Rect(
                100.0,
                100.0,
                300.0,
                500.0
                );

            // LayoutRoot.SetBackgroundContentProvider(m_renderer.CreateContentProvider());
            // LayoutRoot.SetBackgroundManipulationHandler(m_renderer);
        }

        private async Task SetCameraSourceAsync()
        {
            Task t = new Task(() =>
            {
                AppModel model = App.Model;
                model.CameraSync.WaitOne();

                m_renderer.PreviewRotation = model.CameraRotation;
                m_renderer.PreviewFlip = model.CameraFlip;

                m_renderer.PreviewSource = model.CameraSource;
            });

            t.Start();
            await t;
        }


        private async void SwitchButton_Click(object sender, EventArgs e)
        {
            DisableSwitchButton();

            SetStatus(true, "Switching...");

            await SwitchCameraAsync();

            SetStatus(false, null);

            EnableSwitchButton();
        }

        private void DisableSwitchButton()
        {
            if (AppModel.LocationSwitchPossible)
            {
                ApplicationBarIconButton button = (ApplicationBarIconButton)ApplicationBar.Buttons[0];
                if (button != null)
                {
                    button.IsEnabled = false;
                }
            }
        }

        private void EnableSwitchButton()
        {
            if (AppModel.LocationSwitchPossible)
            {
                ApplicationBarIconButton button = (ApplicationBarIconButton)ApplicationBar.Buttons[0];
                if (button != null)
                {
                    button.IsEnabled = true;
                }
            }
        }

        private async Task SwitchCameraAsync()
        {
            AppModel camera = App.Model;

            m_renderer.PreviewSource = null;
            await camera.SwitchLocationAsync();
            await SetCameraSourceAsync();
        }


        private void OpenCapturePage()
        {
            if (m_frame == null)
            {
                m_frame = App.Current.RootVisual as PhoneApplicationFrame;

                if (m_frame != null)
                {
                    m_frameContentWhenOpened = m_frame.Content;

                    m_frame.Navigated += Frame_Navigated;
                    m_frame.NavigationFailed += Frame_NavigationStoppedOrFailed;
                    m_frame.NavigationStopped += Frame_NavigationStoppedOrFailed;

                    m_frame.Navigate(new Uri("/Pages/CapturePage.xaml", UriKind.Relative));
                }
            }
        }

        private void CloseCapturePage()
        {
            if (m_frame != null)
            {
                m_frame.Navigated -= Frame_Navigated;
                m_frame.NavigationFailed -= Frame_NavigationStoppedOrFailed;
                m_frame.NavigationStopped -= Frame_NavigationStoppedOrFailed;

                m_frame = null;
                m_frameContentWhenOpened = null;
            }

            m_capturePage = null;
        }

        private void Frame_Navigated(object sender, NavigationEventArgs e)
        {
            if (e.Content == m_frameContentWhenOpened)
            {
                CloseCapturePage();
            }
            else if (m_capturePage == null)
            {
                m_capturePage = e.Content as CapturePage;
                
                if (m_capturePage != null)
                {
                    if (m_effectIndex >= 0)
                    {
                        m_capturePage.EffectIndex = m_effectIndex;
                    }
                }
            }
        }

        private void Frame_NavigationStoppedOrFailed(object sender, EventArgs e)
        {
            CloseCapturePage();
        }

        
        private void ViewfinderPanel_ManipulationStarted(object sender, ManipulationStartedEventArgs e)
        {
            Point origin = e.ManipulationContainer.TransformToVisual(ViewfinderPanel).Transform(e.ManipulationOrigin);

            if (origin.X >= 0.0 && origin.X <= ViewfinderPanel.ActualWidth &&
                origin.Y >= 0.0 && origin.Y <= ViewfinderPanel.ActualHeight)
            {
                int x = (int)((3.0 * origin.X) / ViewfinderPanel.ActualWidth);
                int y = (int)((3.0 * origin.Y) / ViewfinderPanel.ActualHeight);

                m_effectIndex = y * 3 + x;
                (ViewfinderPanel.Children[m_effectIndex + 1] as Border).Style = Resources["AppImageBorderSelectedStyle"] as Style;
            }
        }

        private void ViewfinderPanel_ManipulationDelta(object sender, ManipulationDeltaEventArgs e)
        {
            Point origin = e.ManipulationContainer.TransformToVisual(ViewfinderPanel).Transform(e.ManipulationOrigin);
            
            int i = -1;
            if (origin.X >= 0.0 && origin.X <= ViewfinderPanel.ActualWidth &&
                origin.Y >= 0.0 && origin.Y <= ViewfinderPanel.ActualHeight)
            {
                int x = (int)((3.0 * origin.X) / ViewfinderPanel.ActualWidth);
                int y = (int)((3.0 * origin.Y) / ViewfinderPanel.ActualHeight);

                i = x + y * 3;
            }

            if (m_effectIndex != i)
            {
                if (m_effectIndex >= 0)
                {
                    (ViewfinderPanel.Children[m_effectIndex + 1] as Border).Style = Resources["AppImageBorderStyle"] as Style;
                }

                m_effectIndex = i;

                if (m_effectIndex >= 0)
                {
                    (ViewfinderPanel.Children[m_effectIndex + 1] as Border).Style = Resources["AppImageBorderSelectedStyle"] as Style;
                }
            }
        }

        private void ViewfinderPanel_ManipulationCompleted(object sender, ManipulationCompletedEventArgs e)
        {
            Point origin = e.ManipulationContainer.TransformToVisual(ViewfinderPanel).Transform(e.ManipulationOrigin);

            if (m_effectIndex >= 0)
            {
                (ViewfinderPanel.Children[m_effectIndex + 1] as Border).Style = Resources["AppImageBorderStyle"] as Style;
            }

            if (origin.X >= 0.0 && origin.X <= ViewfinderPanel.ActualWidth &&
                origin.Y >= 0.0 && origin.Y <= ViewfinderPanel.ActualHeight)
            {
                OpenCapturePage();
            }
        }


        private void SetStatus(bool isWorking, string statusText)
        {
            if (isWorking)
            {
                SystemTray.ProgressIndicator.Text = statusText;
            }

            SystemTray.ProgressIndicator.IsVisible = isWorking;
        }

        private void AboutButton_Click(object sender, EventArgs e)
        {
            NavigationService.Navigate(new Uri("/Pages/AboutPage.xaml", UriKind.Relative));
        }
    }
}